let u = require("Util");

require('customBehavior');
let Behavior = require('TickStreamClass')['Behavior'];

let spawnCreep = new Behavior("spawnCreep",{
    do:function(){
        let creep = this.getCreep();
        //判断creep是否存在
        if(creep != undefined && creep.spawning == false){//检查body
            return;//结束
        }else{//生产creep
            //寻找一个合适的spawn:当前工作所在的房间的spawn

            //找到工作的建筑对象所在房间
            let roomName = u.mget(() => HS.R.getCreep(this.name).working.pos.roomName,undefined);
            if(roomName == undefined){
                for(let i in Game.spawns){roomName = Game.spawns[i].room.name;break;};
            }

            //计算所有spawn房间到建筑对象所在房间的距离
            let bestSpawn;
            let bestDestance = 99999;
            for(let trp in Game.spawns){
                let tr = Game.spawns[trp].room;
                let temp = u.getRoomDistanceByName(tr.name,roomName);
                if(temp == 0){
                    bestSpawn = trp;
                    break;
                }
                if(temp < bestDestance){
                    bestDestance = temp;
                    bestSpawn = trp;
                }
            }
            
            //创建订单
            if(Game.spawns[bestSpawn].createOrder(this.name,true)){
                this.callFn("spawnLoop",bestSpawn);
            }else{
                this.throw(`无法创建 Creep:${this.name} 的生产订单`);
            }
            return;
        }
    },
    exception:function(e){
        switch(e.code){
            case INTENT_FINISHED:
                return;
            default:
                e.printStackTrace(`${this.name} 未处理的异常`);
                return INTENT_RETURN_FAIL;
        }
    },
    spawnLoop:function(spawnName){//判断Spawn是否完成
        let spawn = Game.spawns[spawnName];
        let order = spawn.getOrderState(this.name);
        switch(order){
            case PENDING:
            case SPAWNING:
                return INTENT_RETURN_RECALL;
            case UNRECORDED:
                if(Game.creeps[this.name] != undefined && Game.creeps[this.name].spawning == false){
                    return INTENT_RETURN_TONEXT;
                }
        }

        return INTENT_RETURN_RECALL;
    }
})

let harvestEnergy = new Behavior("harvestEnergy",{
    do:function(targetid){
        let target = Game.getObjectById(targetid);
        this.do("navigateTo",target.pos,{
            range:1
        })

        this.callFn("fullHarvest",new IntentObject(target));
    },
    exception:function(e){
        switch(e.code){
            case ERR_NOT_IN_RANGE:
                return INTENT_RETURN_FAIL;
            case ERR_NOT_ENOUGH_RESOURCES:
                this.stop();
                this.intent(e.intent);
                return INTENT_RETURN_DEFAULT;
            case INTENT_FINISHED:
                return;
            case INTENT_NO_CONTROL_OBJ:
                this.do(spawnCreep);
                return INTENT_RETURN_TONEXT;
            default:
                e.printStackTrace(`${this.name} 未处理的异常`);
                return INTENT_RETURN_FAIL;
        }
    },
    fullHarvest:function(target){
        //判断挖满没
        let creep = this.getCreep();
        if (creep == undefined){
            this.throw(INTENT_NO_CONTROL_OBJ);
            return;
        } 

        if(creep.store.getFreeCapacity(RESOURCE_ENERGY) == 0){
            return INTENT_RETURN_TONEXT;
        }

        //挖
        this.harvest(target);
        return INTENT_RETURN_RECALLNEXT;

    }
})

let fullSpawn = new Behavior('fullSpawn',{
    do:function(targetid){
        this.callFn('fullCheck',targetid);
    },
    exception:function(e){
        switch(e.code){
            case INTENT_FINISHED:
                return;
            case ERR_FULL:
                return;
            default:
                e.printStackTrace(`${this.name} 未处理的异常`);
                return INTENT_RETURN_FAIL;
        }
    },
    fullCheck:function(id){
        let spawn = Game.getObjectById(id);
        if(spawn == null){
            return;
        }

        if(spawn.store[RESOURCE_ENERGY] == spawn.store.getCapacity(RESOURCE_ENERGY)){
            return INTENT_RETURN_TONEXT;
        }

        this.do(getEnergy);
        this.do("navigateTo",spawn.pos,{range:1});
        this.transfer(spawn,RESOURCE_ENERGY);

        return INTENT_RETURN_RECALLNEXT;
    }
})

let fullExtension = new Behavior('fullExtension',{
    do:function(id){
        let extension = Game.getObjectById(id);
        if(extension == null){
            return;
        }
        let creep = this.getCreep();
        if(creep == undefined){
            this.throw(`${this.name} 还没有出生`);
            return;
        }

        if(creep.store[RESOURCE_ENERGY] == 0){
            this.do(getEnergy);
        }
        this.do("navigateTo",extension.pos,{range:1});
        this.transfer(extension,RESOURCE_ENERGY);
    },
    exception:function(e){
        switch(e.code){
            case INTENT_FINISHED:
                return;
            default:
                e.printStackTrace(`${this.name} 未处理的异常`);
                return INTENT_RETURN_FAIL; 
        }
    }
})

let fullTower = new Behavior('fullTower',{
    do:function(id){
        let creep = this.getCreep();
        if(creep == undefined){
            this.throw(`${this.name} 还没有出生`);
            return;
        }
        let tower = Game.getObjectById(id);
        if(creep.store[RESOURCE_ENERGY] == 0){
            this.do(getEnergy);
        }
        this.do("navigateTo",tower.pos,{range:1});
        this.transfer(tower,RESOURCE_ENERGY);
    },
    exception:function(e){
        switch(e.code){
            case INTENT_FINISHED:
                return;
            default:
                e.printStackTrace(`${this.name} 未处理的异常`);
                return INTENT_RETURN_FAIL;
        }
    },
})

let fullController = new Behavior('fullController',{
    do:function(targetid){
        let creep = this.getCreep();
        if(creep == undefined){
            this.throw(INTENT_NO_CONTROL_OBJ);
            return;
        }

        let controller = Game.getObjectById(targetid);
        if(controller == null && creep.room.controller != undefined){
            //使用creep所在房间的
            controller = creep.room.controller;
        }else{
            return;
        }

        if(creep.store[RESOURCE_ENERGY] == 0
        || creep.store.getUsedCapacity(RESOURCE_ENERGY)/creep.store.getCapacity(RESOURCE_ENERGY) < 0.5
        ){
            this.do(getEnergy);
        }

        this.do("navigateTo",controller.pos,{range:3});
        this.callFn("fullCheck",new IntentObject(controller));
    },
    exception:function(e){
        switch(e.code){
            case INTENT_NO_CONTROL_OBJ:
                return INTENT_RETURN_FAIL;
            case INTENT_FINISHED:
                return;
            default:
                e.printStackTrace(`${this.name} 未处理的异常`);
                return INTENT_RETURN_FAIL;
        }
    },
    fullCheck(controller){
        let creep = this.getCreep();
        if(creep == undefined){
            this.throw(INTENT_NO_CONTROL_OBJ);
            return;
        }

        if(creep.store[RESOURCE_ENERGY] == 0){//如果Creep没有能量了
            return INTENT_RETURN_TONEXT;//结束
        }

        this.upgradeController(controller);
        return INTENT_RETURN_RECALLNEXT;
    }
})


//修建筑，参数 full 修到完全ok; once 用完身上能量就结束
let repairStructure = new Behavior('repairStructure',{
    do:function(id,option = {until:"full"}){
        let structure = Game.getObjectById(id);
        if(structure == null || structure.hits == structure.hitsMax){
            return;
        }

        let creep = this.getCreep();
        if(creep == undefined){
            this.throw(INTENT_NO_CONTROL_OBJ);
            return;
        }

        if(creep.store[RESOURCE_ENERGY] == 0){
            this.do(getEnergy);
        }
        this.do("navigateTo",structure.pos,{range:3});
        this.callFn("repairCheck",new IntentObject(structure),option);
    },
    exception:function(e){
        switch(e.code){
            case INTENT_NO_CONTROL_OBJ:
                return INTENT_RETURN_FAIL;
            case INTENT_FINISHED:
                return;
            default:
                e.printStackTrace(`${this.name} 未处理的异常`);
                return INTENT_RETURN_FAIL;
        }
    },
    repairCheck:function(structure,option){
        let creep = this.getCreep();
        if(creep == undefined){
            this.throw(`${this.name} 还没有出生`);
            return;
        }

        if(option.until == "once" && creep.store[RESOURCE_ENERGY] == 0){
            return INTENT_RETURN_TONEXT;
        }else{
            if(creep.store[RESOURCE_ENERGY] == 0){
                this.do(getEnergy);
                this.do("navigateTo",structure.pos,{range:3});
            }
        }

        if(structure.hits < structure.hitsMax){
            if(creep.store[RESOURCE_ENERGY] == 0){
                this.do(getEnergy);
            }
            this.repair(structure);
            return INTENT_RETURN_RECALLNEXT;
        }


        return INTENT_RETURN_TONEXT;
    }
})

//获取能量
let getEnergy = new Behavior("getEnergy",{
    do:function(num){//num 要取得能量的数量 ，想尽一切办法获得能量
        let creep = this.getCreep();
        if(creep == undefined){
            this.throw(`${this.name} 还没有出生`);
            return;
        }

        if(num == undefined){
            num = creep.store.getCapacity(RESOURCE_ENERGY);
        }

        //判断自己有没有那么多能量
        if(creep.store[RESOURCE_ENERGY] > num){
            return;
        }

        //判断自己能不能装得下那么多能量
        if(creep.store.getCapacity(RESOURCE_ENERGY) < num){
            this.say("我装不下那么多能量");
            return;
        }

        this.callFn("fullCheck",num);

    },
    exception:function(e){
        switch(e.code){
            case INTENT_FINISHED:
                return;
            default:
                e.printStackTrace(`${this.name} 未处理的异常`);
                return INTENT_RETURN_FAIL;
        }
    },
    fullCheck:function(num){
        let creep = this.getCreep();
        if(creep == undefined){
            this.throw(`${this.name} 还没有出生`);
            return;
        }

        //判断有没有取满
        if(creep.store[RESOURCE_ENERGY] >= num){
            return;
        }

        //决策去哪里取能量：可以是矿点，可以是容器
        //优先容器
        let boxs = creep.room.find(FIND_STRUCTURES,{
            filter:function(i){
                if(!(i.structureType == STRUCTURE_CONTAINER
                || i.structureType == STRUCTURE_STORAGE)){
                    return false;
                }

                if(i.store[RESOURCE_ENERGY] == 0){
                    return false;
                }
                return true;
            }
        });
        let bestbox = creep.pos.findClosestByRange(boxs);
        if(bestbox != null){
            this.do("navigateTo",bestbox.pos,{range:1});
            this.withdraw(bestbox,RESOURCE_ENERGY);
            return INTENT_RETURN_RECALLNEXT;
        }
        

        //其次矿点，寻找最近的存在能量的矿点，直接在房间内寻找
        let target = creep.pos.findClosestByRange(FIND_SOURCES);
        if(target == null){
            this.throw(`${this.name} 在房间内找不到 Sources`);
            return;
        }
        //导航去
        this.do("navigateTo",target.pos,{
            range:1
        });

        //去挖
        this.do(harvestEnergy,target.id);

        return INTENT_RETURN_RECALL;
    }
})

//建造工地
/**
 * 行为入参
targetid 目标工地的id
option:{
    until: 有3种方式，转移全部能量就结束填：once 需要全部修建知道完成填full
}
 */
let buildConstructionSite = new Behavior("buildConstructionSite",{
    do:function(targetid,option = {until:"full"}){
        let creep = this.getCreep();
        if(creep == undefined){
            this.throw(`${this.name} 还没有出生`);
            return;
        }
        //取能量
        if(creep.store[RESOURCE_ENERGY] == 0){
            this.do(getEnergy);
        }

        //到工地
        let target = Game.getObjectById(targetid);
        this.do("navigateTo",target.pos,{
            range:3
        })
        //修建
        this.callFn("finishCheck",target.id,option);
    },
    exception:function(e){
        switch(e.code){
            case ERR_INVALID_TARGET://一个修好后不能被站的建筑被creep站在上面了
                return INTENT_RETURN_FAIL;
            case INTENT_FINISHED:
                return;
            case INTENT_NO_CONTROL_OBJ:
                this.do(spawnCreep);
                this.intent(e.intent);
                return INTENT_RETURN_TONEXT;
            default:
                e.printStackTrace(`${this.name} 未处理的异常`);
                return INTENT_RETURN_FAIL;
        }
    },
    finishCheck:function(targetid,option){
        let creep = this.getCreep();
        if(creep == undefined){
            this.do(spawnCreep);
            return INTENT_RETURN_RECALL;
        }

        let target = Game.getObjectById(targetid);
        if(target == null){
            return INTENT_RETURN_TONEXT;
        }

        //判断有无完成
        if(target.progress != target.progressTotal){
            if(option.until == "once" && creep.store[RESOURCE_ENERGY] == 0){
                return INTENT_RETURN_TONEXT;
            }
            //判断还有无能量
            if(creep.store[RESOURCE_ENERGY] == 0){
                this.do(getEnergy);//去找能量
                this.do("navigateTo",target.pos,{//然后回来继续
                    range:3
                })
                return INTENT_RETURN_RECALLNEXT;
            }

            this.build(target);
            return INTENT_RETURN_RECALLNEXT;
        }else{
            return INTENT_RETURN_TONEXT;
        }
    }
})

let freeBuild = new Behavior("freeBuild",{
    do:function(){
        let creep = this.getCreep();
        if(creep == undefined){
            this.throw(`${this.name} 还未出生`);
            return;
        }
        //最近的一个修建任务
        let buildSitesPos = [];for(let id in Game.constructionSites){
            buildSitesPos.push(Game.constructionSites[id]);
        }
        let bestBuildSite = creep.pos.findClosestByRange(buildSitesPos);
        if(bestBuildSite != null){
            this.do(buildConstructionSite,bestBuildSite.id,{until:"once"});
        }
    },
    exception:function(e){
        switch(e.code){
            case INTENT_FINISHED:
                return;
            default:
                e.printStackTrace(`${this.name} 未处理的异常`);
                return INTENT_RETURN_FAIL;
        }
    }
})

let freeRepair = new Behavior("freeRepair",{
    do:function(){
        let creep = this.getCreep();
        if(creep == undefined){
            this.throw(INTENT_NO_CONTROL_OBJ);
            return;
        }

        //寻找房间内需要维修的对象
        let targets = creep.room.find(FIND_STRUCTURES,{
            filter:function(i){
                return i.hits != i.hitsMax;
            }
        });

        //寻找最近的
        // let target = creep.pos.findClosestByRange(targets);
        //随机
        let target = targets[Math.floor(Math.random() * targets.length)];
        if(target == null){
            this.say("没有什么好维修的");
            return;
        }
        this.do(repairStructure,target.id,{until:"once"});
    },
    exception:function(e){
        switch(e.code){
            case INTENT_NO_CONTROL_OBJ:
                return INTENT_RETURN_FAIL;
            case INTENT_FINISHED:
                return;
            default:
                e.printStackTrace(`${this.name} 未处理的异常`);
                return INTENT_RETURN_FAIL;
        }
    }
})

let freeTransport = new Behavior("freeTransport",{//把(外矿)能量或其他东西运输到Strage或需要的地方
    do:function(){
        let creep = this.getCreep();
        if(creep == undefined){
            this.throw(`${this.name} 还未出生`);
            return;
        }
        //优先外部矿点，如果外部矿点没有设置传输房间的话，就跳过

        //工作房间内的矿点，如果没有工作，就当前所在房间作为搜索区域
        // let room;
        // if(HS.R.hasCreepWorking(this.name)){
        //     room = HS.R.getCreepWorkingRoom();
        // }else{
        //     room = creep.room;
        // }

        // //如果房间内没有storage就放弃
        // let storage = room.storage;
        // if(storage == null){
        //     return;
        // }

        // //搜索房间内的矿点
        // let containerSites = _.filter(HS.R.getRoomStructures(room),(i) => i.structureType == STRUCTURE_CONTAINER);

        // //搜索最近的
        // let containerSite = creep.pos.findClosestByRange(containerSites);

        // //获取其中 还有资源的 Containers
        // let containers = _.filter(containerSite.getSources(),(i) => i.store.getUsedCapacity()>0);
        // let container = containers[0];

        // //决定拿什么
        // let type;for(let name in container.store){type = name;break;};

        // //导航去
        // this.do("navigateTo",containers[0].pos,{range:1});

        // //取出
        // this.withdraw(container,type);

        // //去storage
        // this.do("navigateTo",storage.pos,{range:1});

        // this.transfer(storage,type);

        // 优先将能量给Tower
        let towers = creep.room.find(FIND_MY_STRUCTURES,{
            filter:function(i){
                return i.structureType == STRUCTURE_TOWER && (i.store[RESOURCE_ENERGY] < i.store.getCapacity(RESOURCE_ENERGY));
            }
        })
        if(towers.length > 0){
            this.do(fullTower,towers[0].id);
        }

        
    },
    exception:function(e){
        switch(e.code){
            case INTENT_FINISHED:
                return;
            default:
                e.printStackTrace(`${this.name} 未处理的异常`);
                return INTENT_RETURN_FAIL;
        }
    }
})


//================= 主要行为入口

//空闲行为
let free = new Behavior("free",{
    do:function(){
        switch(Math.ceil(Math.random()*7)){
            case 1://做做修建任务
            case 2:
                this.say("搞搞修建？");
                this.do(freeBuild);
                break;
            case 3://做做维修任务
            case 4:
                this.say("搞搞维修？");
                this.do(freeRepair);
                break;
            case 5://做做运输任务
            case 6:
                this.say("搞搞运输？");
                this.do(freeTransport);
                break;
            case 7://冲RCL!
                this.say("冲RCL");
                this.do(fullController);
                break;
        }
    },
    exception:function(e){
        switch(e.code){
            case INTENT_FINISHED:
                return;
            default:
                e.printStackTrace(`${name} 未解决的异常`);
                return INTENT_RETURN_FAIL;
        }
    }
})

//controller的主工作行为
let controller = new Behavior("controller",{
    do:function(){
        let creep = this.getCreep();
        if(creep == undefined){
            this.throw(INTENT_NO_CONTROL_OBJ);
            return;
        }

        let working = HS.R.getCreep(this.name).working;

        //优先房间内的修建任务，维护任务
        let targets = _.filter(Game.constructionSites,function(site){
            return site.pos.roomName == working.pos.roomName;
        })
        if(targets.length > 0){
            this.do(buildConstructionSite,targets[0].id);
            return;
        }

        //其次是房间外的修建任务
        targets = _.filter(Game.constructionSites,(site) => {
            if(site.pos.roomName == working.pos.roomName){
                return false;
            }

            //且距离不能大于3
            if(u.getRoomDistanceByName(working.pos.roomName,site.pos.roomName) > 3){
                return false;
            }

            return true;
        });
        if(targets.length > 0){
            this.do(buildConstructionSite,targets[0].id);
            return;
        }

        //判断自己该去upgrade还是去harvest
        this.callFn('harvestCheck');

        //导航去upgrade
        let controllerP = Game.rooms[working.pos.roomName].controller.pos;//找到Controller
        this.do("navigateTo",controllerP,{
            range:3
        });

        //升级到满
        this.callFn('fullUpgrade',new IntentObject(creep.room.controller));
        
        this.do(free);
    },
    exception:function(e){
        switch(e.code){
            case INTENT_FINISHED:
                return INTENT_RETURN_DEFAULT;
            case "NO_CARRY_BODY"://如果没有Carry Body
                e.printStackTrace(this.name + " 没有 CARRY 部件");
                return INTENT_RETURN_FAIL;
            case INTENT_NO_CONTROL_OBJ:
                return INTENT_RETURN_FAIL;
            default:
                e.printStackTrace(this.name + "未处理的异常");
                return INTENT_RETURN_FAIL;
        }
    },
    harvestCheck(){//决策是否要去harvest，如果要就直接去，并且挖满
        let creep = this.getCreep()
        if (creep == undefined){
            this.throw(INTENT_NO_CONTROL_OBJ);
            return;
        } 

        //检查自己有没有Carry部件
        let countOfCarry = 0;
        for(let part of creep.body){
            if(part.type == CARRY){
                countOfCarry++;
            }
        }
        
        if(countOfCarry <= 0){
            this.throw("NO_CARRY_BODY");
            return INTENT_RETURN_TONEXT;
        }

        //计算自己身上含有能量的比例
        let p = creep.store.getUsedCapacity(RESOURCE_ENERGY)/creep.store.getCapacity(RESOURCE_ENERGY);

        if(p < 0.3){//如果身上的能量小于30%就去挖满了来
            this.do(getEnergy);
        }

        return INTENT_RETURN_TONEXT;
    },
    fullHarvest:function(target){
        //判断挖满没
        let creep = this.getCreep();
        if (creep == undefined){
            this.throw(INTENT_NO_CONTROL_OBJ);
            return;
        } 

        if(creep.store.getFreeCapacity(RESOURCE_ENERGY) == 0){
            return INTENT_RETURN_TONEXT;
        }

        //挖
        this.harvest(target);
        return INTENT_RETURN_RECALLNEXT;

    },
    fullUpgrade:function(controller){
        let creep = this.getCreep();
        if (creep == undefined){
            this.throw(INTENT_NO_CONTROL_OBJ);
            return;
        } 
        //判断能量是否用完
        if(creep.store.getUsedCapacity(RESOURCE_ENERGY) > 0){
            this.upgradeController(controller);
            return INTENT_RETURN_RECALLNEXT;
        }
        return INTENT_RETURN_DEFAULT;
    }
    
})

//spawn的主工作行为
let spawn = new Behavior("spawn",{
    do:function(){
        let creep = this.getCreep();
        if(creep == undefined){
            this.do(spawnCreep);
        }

        let working = HS.R.getCreep(this.name).working;

        //优先填spawn能量
        let myspawnid = working.id;
        this.do(fullSpawn,myspawnid);

        //其次是extension
        let extensions = creep.room.find(FIND_MY_STRUCTURES,{
            filter:function(i){
                return i.structureType == STRUCTURE_EXTENSION && (i.store.getCapacity(RESOURCE_ENERGY) != i.store[RESOURCE_ENERGY]);
            }
        });
        if(extensions.length != 0){
            //最近的
            let extension = creep.pos.findClosestByRange(extensions);
            this.do(fullExtension,extension.id);
            return;
        }
        

        //最后是修extension ，寻找房间内所有extension的工地
        let targets = _.filter(Game.constructionSites,(site) => site.structureType == STRUCTURE_EXTENSION)
        if(targets.length > 0){
            this.do(buildConstructionSite,targets[0].id,{
                until:"once"
            });
            return;
        }

        this.do(free);
    },
    exception:function(e){
        switch(e.code){
            case INTENT_FINISHED:
                let creep = this.getCreep();
                if(creep == undefined){
                    return INTENT_RETURN_FAIL;
                }
                let targets = _.filter(Game.constructionSites,(site) => site.structureType == STRUCTURE_EXTENSION)
                let extensions = creep.room.find(FIND_MY_STRUCTURES,{
                    filter:function(i){
                        return i.structureType == STRUCTURE_EXTENSION && (i.store.getCapacity(RESOURCE_ENERGY) != i.store[RESOURCE_ENERGY]);
                    }
                });
                if(targets.length == 0 && extensions.length == 0){//允许下岗
                    return;
                }

                this.do(spawn);
                return;
            case ERR_FULL:
                return;
            default:
                e.printStackTrace(`${this.name} 未处理的异常`);
                return INTENT_RETURN_FAIL;
        }
    },
})

//container的行为
let container = new Behavior("container",{
    do:function(){
        let creep = this.getCreep();
        if(creep == undefined){
            this.throw(INTENT_NO_CONTROL_OBJ);
            return;
        }

        let working = HS.R.getCreep(this.name).working;
        let home = Game.getObjectById(working.id);
        if(home == undefined){//说明在外矿工作或自己主container不在了，先去外矿所在地址
            if(working.pos.roomName != creep.pos.roomName){//说明在外矿
                this.do("navigateTo",working.pos);
                return;
            }else{//说明container不在了

                //检查有无工地
                let pos = new RoomPosition(working.pos.x,working.pos.y,working.pos.roomName);
                let atSite = undefined;
                for(let id in Game.constructionSites){
                    let tempSite = Game.constructionSites[id];
                    if(tempSite.structureType == STRUCTURE_CONTAINER
                    && tempSite.pos.roomName == pos.roomName
                    && tempSite.pos.x == pos.x
                    && tempSite.pos.y == pos.y){
                        atSite = tempSite;
                    }
                }
                if(atSite == undefined){
                    //创建工地
                    Game.rooms[working.pos.roomName].createConstructionSite(working.pos.x,working.pos.y,STRUCTURE_CONTAINER);
                    this.stop();
                    return;
                }

                //修建工地
                this.do(buildConstructionSite,atSite.id);
                return;
            }
        }

        //检查是否需要维修的Container
        let containers = home.getContainers();
        for(let i of containers){
            if(i.hits/i.hitsMax < 0.7){
                this.do(repairStructure,i.id);
            }
        }


        
        //寻找驻点附近最近的矿点
        let targets = home.getSources();
        if(targets.length > 0){//有矿点
            this.do(harvestEnergy,targets[0].id);
        }else{//没有矿点
            this.say("找不到矿点");
            //尝试刷新
            home.refershArea();
            return;
        }

        //决定是否运输
        containers = _.filter(home.getContainers(),(i) => i.store.getFreeCapacity(RESOURCE_ENERGY) != 0);

        if(containers.length > 0 && creep.store[RESOURCE_ENERGY] > 0){//不进行运输
            this.do("navigateTo",containers[0].pos,{range:1});
            this.transfer(containers[0],RESOURCE_ENERGY);
            return;
        }else if(containers.length == 0){//进行运输
            this.say("进行运输！");
            return;
        }
    },
    exception(e){
        switch(e.code){
            case INTENT_NO_CONTROL_OBJ:
                return INTENT_RETURN_FAIL;
            case INTENT_FINISHED:
                this.do(container);
                return;
            case ERR_FULL:
                return;
            default:
                e.printStackTrace(`${this.name} 未处理的异常`);
                return INTENT_RETURN_FAIL;
        }
    }
})

//Storage的行为
let storage = new Behavior("storage",{
    do:function(){
        let creep = this.getCreep();
        if(creep == undefined){
            this.throw(INTENT_NO_CONTROL_OBJ);
            return;
        }

        //寻找矿点
        //工作房间内的矿点
        let working = HS.R.getCreep(this.name).working;
        let room = Game.rooms[working.pos.roomName];

        //如果房间内没有storage就放弃
        let storage = room.storage;
        if(storage == null){
            return;
        }

        //如果身上有东西，先放了来
        if(creep.store.getUsedCapacity() > 0){
            this.do("navigateTo",storage.pos,{range:1})
            // 转移所有资源
            for(let resourceType in creep.store) {
                this.transfer(storage, resourceType);
            }
        }

        //搜索附近的矿点
        let containerSites = u.mapToArray(HS.R.getRoomStructures(room.name),function(seter,key,value){
            if(value.type != STRUCTURE_CONTAINER){
                return;
            }
            let o = Game.getObjectById(key);
            
            if(o != null){
                seter(o);
            }
        })

        //搜索最近的
        let containerSite = creep.pos.findClosestByRange(containerSites);

        let container;
        //获取其中 还有资源的 Containers
        if(containerSite != null){
            let containers = _.filter(containerSite.getContainers(),(i) => i.store.getUsedCapacity()>0);
            let used = 0;
            let moreContentContainer;//寻找资源最多的 但不小于50%的，留点可用的给别人
            for(let i of containers){
                let u = i.store.getUsedCapacity();
                if(u >= used && i.store.getUsedCapacity()/i.store.getCapacity() > 0.5){
                    used = u;
                    moreContentContainer = i;
                }
            }
            container = moreContentContainer;
        }
        
        if(container == undefined){//寻找外矿目标点
            this.say("好像都运完了");

            let lists = [];
            for(let roomName in Game.rooms){
                lists = lists.concat(u.mapToArray(HS.R.getRoomStructures(roomName),function(seter,key,value){
                    if(value.type != STRUCTURE_CONTAINER){
                        return;
                    }
                    let o = Game.getObjectById(key);
                    if(o == null){
                        return;
                    }
                    if(o.pos.roomName == storage.pos.roomName){
                        return;
                    }

                    seter(o);
                }));
            }

            if(lists.length == 0){
                this.do(free);
                return;
            }

            //随机确定一个
            this.say("前往外矿运输资源");
            container = lists[Math.floor(Math.random() * lists.length)]; 
        }

        //决定拿什么
        let type;for(let name in container.store){type = name;break;};

        //导航去
        this.do("navigateTo",container.pos,{range:1});

        //取出
        this.withdraw(container,type);

        //去storage
        this.do("navigateTo",storage.pos,{range:1});

        this.transfer(storage,type);

    },
    exception(e){
        switch(e.code){
            case INTENT_NO_CONTROL_OBJ:
                return INTENT_RETURN_FAIL;
            case INTENT_FINISHED:
                this.do(storage);
                return;

            default:
                e.printStackTrace(`${this.name} 未解决的异常`);
                return INTENT_RETURN_FAIL;
        }
    }
})

let homesteadDefault = new Behavior("homesteadDefault",{
    do:function(){
        let creep = this.getCreep();

        //判断是否自己存在协议 Protocol


        //寻找自己的工作
        let working = HS.R.getCreep(this.name).working;
        if(working == undefined){//如果没有工作
            //是否允许空闲
            if(HS.R.isFree(this.name)){//允许空闲就设置空闲行为
                if(creep == undefined || creep.spawning){//但creep没有实体
                    //出生creep
                    this.do(spawnCreep);
                }
                this.do(free);
                return;
            }else{
                this.stop();//防止无限循环
                return;
            }
        }

        //到这里表示creep有工作
        if(creep == undefined || creep.spawning){//但creep没有实体
            //出生creep
            this.do(spawnCreep);
        }

        //根据工作指明之后的行为
        this.do(working.type);
    },
    exception:function(e){
        switch(e.code){
            case INTENT_FINISHED://注意，这种情况已经出栈了，若要在当前Scope操作请在 do 结尾使用callFn
                this.setBehaviorObject(homesteadDefault);
                return;
            default:
                e.printStackTrace(`${this.name} 未处理的异常`);
                return INTENT_RETURN_FAIL;
        }
    },
})


//============== 标准协议
/**
 * 协议和行为的区别和共同点，协议和行为都是描述一系列动作
 * 但协议大部分情况是由玩家通过控制台发起，并自动结束或由玩家结束
 * 行为则是Creep自己判断调用和结束
 * 协议允许设置 Homestead 的相关变量，调用 Homestead 的全部方法
 * 
 * 另外，协议最大的特点就是，不只针对某一个Creep起作用，它允许同时控制其他Creep
 * 
 * 其次，协议的主体是个虚拟的creep，所以一般不用this，只是利用TickStream的跨tick功能
 * 
 * 例如，基本控制协议，外矿开发协议，进攻协议，防守协议，市场交易协议
 */

 
 /**
  * 房间保护协议，启用该协议，使用HS.launchProtocol("roomProtectProtocol");其他的协议同理
  * 当遭受外来入侵时，该协议超控(覆盖Behavior)让所有工作creep进行躲避拉扯，绕开攻击者或是离开房间
  * 并调集周边房间的资源生成反制单位来抵抗进攻
  * 稳定后解除超控,creep将会返回原来的房间
  * 
  * 如果cpu不够用，会强行对一些房间设置时间膨胀
  * 
  */

let roomProtectProtocolLeave = new Behavior('roomProtectProtocolLeave',{
    do:function(){
        let creep = this.getCreep();
        if(creep == undefined){
            this.throw(INTENT_NO_CONTROL_OBJ);
            return;
        }
        this.say("溜溜球！",true);
    },
    exception(e){
        switch(e.code){
            case INTENT_NO_CONTROL_OBJ:
                return INTENT_RETURN_FAIL;
            case INTENT_FINISHED:
                return;
            default:
                e.printStackTrace(`${this.name} 未处理的异常`);
                return INTENT_RETURN_FAIL;
        }
    }
})
let roomProtectProtocolBackup = new Behavior('roomProtectProtocolBackup',{
    do:function(){
        let creep = this.getCreep();
        if(creep == undefined){
            this.throw(INTENT_NO_CONTROL_OBJ);
        }

        /**
         * 后勤动作详情
         * 跑得快的将所有资源运送给房间内的作战单位，其他creep躲进Rampart 如果没有，就跑到房间外面去
         */

        this.intent([INTENT_SYNC,2]);
        this.say("后勤支援！",true);


        //目前暂时的方案是离开房间
        this.do(roomProtectProtocolLeave);
        return;
        //获取有需求的tower
        //tower需要能量了会发布订单
        let selfCapacity = creep.store.getCapacity(RESOURCE_ENERGY);
        let towers = room.find(FIND_MY_STRUCTURES,{
            filter:function(i){
                return i.structureType == STRUCTURE_TOWER && i.store.getFreeCapacity(RESOURCE_ENERGY) > selfCapacity
            }
        });

    },
    exception(e){
        switch(e.code){
            case INTENT_NO_CONTROL_OBJ:
                return INTENT_RETURN_FAIL;
            case INTENT_FINISHED:
                return;
            default:
                e.printStackTrace(`${this.name} 未处理的异常`);
                return INTENT_FINISHED;
        }
    }
})
let roomProtectProtocol = new Behavior('roomProtectProtocol',{
    do:function(){
        console.log(this.name + " 协议已就绪，正在监听");
        this.callFn("loop");
    },
    exception(e){
        switch(e.code){
            case INTENT_FINISHED:
                this.stop();
                this.do(roomProtectProtocol);
                return;
            default:
                r.printStackTrace(`协议出现未处理的异常`);
                return INTENT_RETURN_FAIL;
        }
    },
    loop:function(){
        
        let whiteList = ["SP1CE"];

        //获取房间敌人
        let roomTargets = {};
        let isSafe = true;
        for(let roomName in Game.rooms){
            let room = Game.rooms[roomName];
            let whiteListTargets = [];
            let targets = room.find(FIND_HOSTILE_CREEPS,{
                filter:function(i){
                    if(whiteList.indexOf(i.owner.name) != -1){//在白名单
                        whiteListTargets.push(i);
                        return false;
                    }
                    return true;
                }
            });

            if(whiteListTargets.length > 2){
                targets = targets.concat(whiteListTargets);
            }

            if(targets.length > 0){
                isSafe = false;
                roomTargets[roomName] = targets;
            }
            
        }

        if(isSafe){//情况安全
            this.stop(5);//每5tick进行一次
            return INTENT_RETURN_RECALL;
        }

        for(let name in roomTargets){//通报消息
            if(Game.time % 3 == 0){
                console.log(`房间 ${name} 正在受到威胁`);
            }
        }

        //超控Creep：将受威胁房间所有creep进入作战状态，覆盖行为
        for(let name in Memory.creeps){
            let creep = T.R.creeps[name];
            let creepR = Game.creeps[name];

            if(creepR != undefined && creep != undefined
            && roomTargets.hasOwnProperty(creepR.pos.roomName)
            && creep.getBehaviorName() != "roomProtectProtocolBackup"){
                creep.setBehavior("roomProtectProtocolBackup");
            }
        }


        //寻找反制手段
        for(let name in roomTargets){
            let room = Game.rooms[name];
            if(room == undefined){
                continue;
            }
            let targets = roomTargets[name];
            //分类目标
            targets = u.classifyArray(targets,{
                heal:(i) => i.getActiveBodyparts(HEAL) > 0,
                attacker:(i) => i.getActiveBodyparts(ATTACK) > 0 || i.getActiveBodyparts(RANGED_ATTACK) > 0,
                worker:(i) => i.getActiveBodyparts(WORK) > 0 || i.getActiveBodyparts(CLAIM) > 0,
                unknow:(i) => true
            })
            
            //寻找房间内的Tower
            let towers = room.find(FIND_MY_STRUCTURES,{
                filter:function(i){
                    return i.structureType == STRUCTURE_TOWER;
                }
            });

            //为每个tower分配目标
            for(let tower of towers){
                for(let type in targets){
                    if(targets[type].length > 0){
                        tower.attack(targets[type][0]);
                        break;
                    }
                }
            }
        }
        
        return INTENT_RETURN_RECALL;
    }
})



let outRoomSourceDevelopmentProtocol = new Behavior("outRoomSourceDevelopmentProtocol",{
    do:function(sourcePosition){
        this.say("执行协议中...");
    },
    exception:function(e){
        switch(e){
            case INTENT_FINISHED:
                return;
            default:
                e.printStackTrace(`${this.name} 未处理的异常`);
        }
    }
})